package timit;

import core.HiddenLayer;
import core.Phone;
import core.Speaker;

import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: lahiru
 * Date: 6/11/14
 * Time: 4:07 PM
 * To change this template use File | Settings | File Templates.
 */
public class CollectPdfStats {

    private static final int numberOfLayers = 5;
    private static final String hiddenActivationDir = "/home/lahiru/experiments/Speaker-effects/activations/train/";
    private static final String pdfAlignmentsDir = "/home/lahiru/experiments/Speaker-effects/alignments/";
    private static final String saveObjects = "/home/lahiru/experiments/Speaker-effects/objects/train/";
    private static final String listOfSpeakers = "FALK0 FALR0 FBCG1 FBCH0 FBJL0 FCDR1 FCEG0 FCKE0 FCMM0 FDFB0 MCAE0 " +
            "MCAL0 MCHL0 MCSS0 MCTH0 MCTM0 MDBP0 MDCD0 MDHS0 MDLC2";
    private static final int numberOfHiddenUnits=1024;

    public static void main(String[] args) {
        List<String> speakers = (Arrays.asList(listOfSpeakers.split(" ")));

        for (int i = 1; i <= numberOfLayers; i++) {
            System.out.println(" Start processing the layer " + i);
            HiddenLayer hiddenLayer = new HiddenLayer(i);

            for(String spk:speakers){

                int finalFrameCount = 0;
                Speaker speaker = new Speaker();
                speaker.setId(spk);

                String ha = hiddenActivationDir + "h" + i + "/activations_" + spk + ".ark";
                String pAlignments = pdfAlignmentsDir + "pdf." + spk +".ark";

                System.out.println(" Reading the activation file  " + ha + " for the speaker " + spk);
                System.out.println(" phone labels are in  " + pAlignments + " for the speaker " + spk);

                //Read pdf-alignments line by line, file contains a line per utterance.

                try {
                    BufferedReader phonesBr = new BufferedReader(new FileReader(pAlignments));
                    String line;
//                    List<Integer> phoneList = new ArrayList<Integer>();


                    //Now for each utterance read the hidden activations frame by frame.
                    BufferedReader haBr = new BufferedReader(new FileReader(ha));
                    String line1;

                    int utteranceCount = 0;
                    int frameCount = 0;
                    String frameUtterance = "";
                    String utterance = "";


                    //read a line from the pdf-alignments for each frame in the utterance
                    while ((line = phonesBr.readLine()) != null) {
                        String phoneIds[] = line.split(" ");
                        utterance = phoneIds[0];
                        while ((line1 = haBr.readLine()) != null) {

                            String hArray[] = line1.trim().split(" ");

                            if (hArray.length == 3) {  //starting of an utterance
                                utteranceCount = utteranceCount + 1;
                                frameCount = 0;
                                frameUtterance = hArray[0];

                                String tempArray[] = null;
                                String line2 = "";

                                if (!frameUtterance.equalsIgnoreCase(utterance)) {
                                    System.err.println("The frame utterance " + frameUtterance);
                                    System.err.println("The phone utterance " + utterance);

                                    do {
                                        line2 = haBr.readLine();
                                        tempArray = line2.trim().split(" ");

                                    } while (tempArray.length != 3);

                                    System.err.println("The new frame utterance is " + tempArray[0]);

                                }

                            } else if (hArray.length == numberOfHiddenUnits) {  //intermediate frame
//                                speaker.addFrameStats(phoneList.get(frameCount), hArray);
                                speaker.addFrameStats(Integer.parseInt(phoneIds[frameCount + 1]), hArray);
                                frameCount = frameCount + 1;
                            } else if (hArray.length == numberOfHiddenUnits + 1) {   //last frame of the utterance
                                speaker.addFrameStats(Integer.parseInt(phoneIds[frameCount + 1]), Arrays.copyOfRange(hArray, 0, hArray.length - 1));
//                                speaker.addFrameStats(phoneList.get(frameCount), Arrays.copyOfRange(hArray, 0, hArray.length - 1));
                                frameCount = frameCount + 1;
                                finalFrameCount = finalFrameCount + frameCount;
                                break;
                            } else {
                                System.err.println("This is not possible " + hArray.length);
                            }
                        }
                    }
                    haBr.close();
                    System.out.println(" The utterance count " + utteranceCount);
                    System.out.println(" The finalFrameCount " + finalFrameCount);

                    phonesBr.close();
                } catch (IOException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

                //Printout speaker data,
                int totalPhoneCount = 0;
                Map<Integer, Phone> phones = speaker.getPhones();
                for (int pid : phones.keySet()) {
                    Phone phone = phones.get(pid);
                    //phone.averageVector(); //TODO should only do once when finished
                    int count = phone.getCount();
                    totalPhoneCount = totalPhoneCount + count;
//                    System.out.println("phone id " + pid + " count " + count);
                }

                if (totalPhoneCount != finalFrameCount) {
                    System.err.println(" There is a mismatch of frames for the " + speaker.getId());
                } else {
                    System.out.println("Frame counts are matching for the  " + speaker.getId());
                }


                hiddenLayer.getSpeakerList().add(speaker); //add the current speaker to the hidden layer


            }

            //save the hidden layer data
            String location = null;
            try {
                location = saveObjects + "h" + i + ".ser";
                FileOutputStream fileOut =
                        new FileOutputStream(location);
                ObjectOutputStream out = new ObjectOutputStream(fileOut);
                out.writeObject(hiddenLayer);
                out.close();
                fileOut.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
            System.out.println("Serialized data is saved in " + location + " for " + hiddenLayer.getSpeakerList().size() + " speakers ");

        }
    }



}
